package middleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"net/http"
	"peilian-api/app/global/common"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/log"
	"peilian-api/app/global/variable"
	"time"
)

func ThirdBox() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			authExists bool
			err        error
			useFull    bool
		)
		defer func() {
			if !authExists {
				c.JSON(http.StatusOK, gin.H{
					"code": 403,
					"data": struct{}{},
					"msg":  "No Auth",
				})
				c.Abort()
				return
			}
			if useFull {
				c.JSON(http.StatusOK, gin.H{
					"code": 420,
					"data": struct{}{},
					"msg":  "Full user",
				})
				c.Abort()
				return
			}
			if err != nil {
				c.JSON(http.StatusOK, gin.H{
					"code": 500,
					"data": struct{}{},
					"msg":  fmt.Errorf("service error:%s", err.Error()),
				})
				c.Abort()
				return
			}
		}()
		agentId, authExists := c.Get("aid")
		if !authExists {
			return
		}
		source, authExists := c.Get("source")
		if !authExists {
			return
		}
		uid, authExists := c.Get("uid")
		if !authExists {
			return
		}
		if agentId.(uint) == 0 || source.(string) == "" {
			c.Next()
			return
		}
		// 盒子更新时间
		if source.(string) == "box" {
			redisConcurrentKey := fmt.Sprintf(common.RedisAgentLoginUsers, agentId.(uint))
			currentTime := time.Now().Format(common.DateTimeFormat)
			uidStr := fmt.Sprintf("%d", uid.(uint))
			v, err := variable.DB.Redis.HGet(redisConcurrentKey, uidStr).Result()
			if err != nil {
				return
			}
			t, err := time.ParseInLocation(common.DateTimeFormat, v, time.Local)
			if err != nil {
				if err == redis.Nil {
					authExists = false
					return
				}
				return
			}
			if time.Now().Unix() > t.Add(common.BoxExpirationTime).Unix() {
				authExists = false
				return
			}

			variable.DB.Redis.HSet(redisConcurrentKey, uidStr, currentTime)
		}
		// 第三方登录拦截题目获取
		if source.(string) == "third" {
			//redisUserKey := fmt.Sprintf(common.RedisAppletsUser, uid.(uint))
			//redisUsersSetKey := fmt.Sprintf(common.RedisAppletsUserSet, agentId.(uint))

			if c.FullPath() == "/question/groups" {
				// todo 小程序并发暂时不用 >>>>
				//// 判断当前id 是否在集合
				//exist, _ := variable.DB.Redis.SIsMember(redisUsersSetKey, uid).Result()
				//if exist {
				//	goto addThirdCatch
				//}
				//// 获取缓存的agent信息
				//redisCatchKey := fmt.Sprintf(common.RedisAgentCatch, agentId.(uint))
				//agent := tables.Agent{}
				//v, err := variable.DB.Redis.Get(redisCatchKey).Result()
				//if err != nil {
				//	// 从数据库获取
				//	d := variable.DB.MySQL.Model(tables.Agent{}).Where("id = ?", agentId).First(&agent)
				//	if d.Error != nil || agent.ID == 0 {
				//		return
				//	}
				//	b, _ := json.Marshal(agent)
				//	variable.DB.Redis.Set(redisCatchKey, string(b), time.Minute*10)
				//} else {
				//	err = json.Unmarshal([]byte(v), &agent)
				//	if err != nil {
				//		log.Logger.ErrorF(c, "Unmarshal error:", err.Error())
				//		return
				//	}
				//}
				//if agent.AppletsConcurrent == 0 {
				//	useFull = true
				//	return
				//}
				//userCount, err := variable.DB.Redis.SCard(redisUsersSetKey).Result()
				//if err != nil {
				//	log.Logger.ErrorF(c, "ZCard error:", err.Error())
				//	return
				//}
				//if int(userCount) >= agent.AppletsConcurrent {
				//	useFull = true
				//	return
				//}
				// <<<<<<<<<<
				// 获取用户信息
				user, err := tables.GetUserInfoById(int(uid.(uint)))
				if err != nil {
					log.Logger.ErrorF(c, "get user info error:", err.Error())
					return
				}
				if user.UseAppletsEndTime.Before(time.Now()) {
					authExists = false
					return
				}
			}
			//	// 缓存
			//	variable.DB.Redis.SAdd(redisUsersSetKey, uid)
			//addThirdCatch:
			//	currentTime := time.Now().Format(common.DateTimeFormat)
			//	variable.DB.Redis.Set(redisUserKey, currentTime, common.BoxExpirationTime)
		}
		c.Next()
	}
}

//// DelSetData 小程序端并发的方式 暂时不需要了
//func DelSetData() {
//	// 获取所有的agent 信息
//	var agents []tables.Agent
//	d := variable.DB.MySQL.Model(tables.Agent{}).Select("ID").Find(&agents)
//	if d.Error != nil {
//		fmt.Println("select agent error: " + d.Error.Error())
//		return
//	}
//	for _, a := range agents {
//		redisUsersSetKey := fmt.Sprintf(common.RedisAppletsUserSet, a.ID)
//		uIds, err := variable.DB.Redis.SMembers(redisUsersSetKey).Result()
//		if err != nil {
//			fmt.Printf("get redis %s error: %+v\n", redisUsersSetKey, err)
//			continue
//		}
//		for _, uid := range uIds {
//			uidInt, _ := strconv.Atoi(uid)
//			redisUserKey := fmt.Sprintf(common.RedisAppletsUser, uidInt)
//			_, err = variable.DB.Redis.Get(redisUserKey).Result()
//			if err != nil {
//				if err == redis.Nil {
//					variable.DB.Redis.SRem(redisUsersSetKey, uid)
//				} else {
//					fmt.Printf("get redis %s error: %+v\n", redisUserKey, err)
//				}
//			}
//		}
//	}
//}
